#!/usr/bin/env python

import cherrypy, os, threading, time, platform

from html5 import Html5, Q
from deck import Deck, Card, Player

Card.ROOT = '/img/cardset-gdkcard-bonded'
class Deck99(Deck):
    def discard(self, suit, rank):
        return rank in ('two', 'three', 'four', 'five')

BID_VALUE = {'clubs': 3, 'hearts': 2, 'spades': 1, 'diamonds': 0}

class Global:
    deck = Deck99()
    hands = {}
    bids = {}
    playerid = 0
    dealt = False

lock = threading.RLock() # protect globals
def protect(f):
    def newf(*args, **kwds):
        with lock:
            result = f(*args, **kwds)
        return result
    return newf

class View(Html5):

    @protect
    def index(self):
        self.h1('Welcome to the 99 Game Server')
        if len(Global.hands)==3:
            self.h2('Server Full .. try again later')
        else:
            Global.deck.shuffle()
            self.h2(Q.a('Click to shuffle', href='/'))
        self.div()
        for idx, card in enumerate(Global.deck):
            self.img(src=card.image_file).noclose()
            if idx % 12 == 11:
                self.div.close()
                self.div()
        self.div.close()
        self.h2(Q.a('Click to join game', href='/join'))
        return self

    @protect
    def find_me(self):
        if len(Global.hands)<3:
            name = 'player-%s' % (Global.playerid)
            Global.playerid += 1
            Global.hands[name] = Player(name)
            Global.bids[name] = Player('bid-%s' % name)
            return name

    @protect
    def wait_for_deal(self, me):
        if len(Global.hands)==3 and not Global.dealt:
            Global.deck.shuffle()
            Global.deck.deal(Global.hands.values())
            Global.dealt = True
        if len(Global.hands)==3:
            Global.hands[me].sort()
            return Global.hands[me]

    @protect
    def my_cards(self, name):
        return Global.hands[name], Global.bids[name]

    def _bidding(self, name, hand, bids):
        self.h1('Bidding %s' % name)
        nbid = len(bids)
        if nbid==0:
            self.h2('Select a card to bid')
        elif nbid<3:
            self.h2('Select a card to bid or, Click bid card to unbid')
        elif nbid==3:
            self.h2('Complete bidding or, Click bid card to unbid')
        self.h2('Your Hand')
        hand.sort()
        for card in hand:
            if nbid<3:
                self.img(src=card.image_file, onclick="location.href='/bid/%s/%s'" % (name, card)).noclose()
            else:
                self.img(src=card.image_file).noclose()
        if bids:
            self.div().close()
            self.h2('Your Bids')
            bids.sort()
            total = 0
            for card in bids:
                self.img(src=card.image_file, onclick="location.href='/unbid/%s/%s'" % (name, card)).noclose()
                total += BID_VALUE[card.suit]
            self.h2('Bid value %s' % total)
            if nbid==3:
                self.h2(Q.a('Click to complete bidding', href='/play/%s' % name))
        return self

    @protect
    def validate(self, name):
        if not name in Global.hands:
            raise cherrypy.HTTPRedirect('/')

    def join(self):
        name = self.find_me()
        if not name:
            raise cherrypy.HTTPRedirect('/')
        while True:
            hand = self.wait_for_deal(name)
            if hand:
                break
            time.sleep(1)
        hand, bids = self.my_cards(name)
        return self._bidding(name, hand, bids)

    def bid(self, name, card):
        self.validate(name)
        hand, bids = self.my_cards(name)
        hand.give(bids, hand.find(card))
        return self._bidding(name, hand, bids)

    def unbid(self, name, card):
        self.validate(name)
        hand, bids = self.my_cards(name)
        bids.give(hand, bids.find(card))
        return self._bidding(name, hand, bids)

    @protect
    def remove_me(self, name):
        Global.dealt = False
        hand = Global.hands.pop(name)
        hand.give_all(Global.deck)
        bid = Global.bids.pop(name)
        bid.give_all(Global.deck)

    def play(self, name):
        self.validate(name)
        self.h1(name)
        self.remove_me(name)
        self.h2(Q.a('Click when done', href='/'))
        return self

class Cards(object):

    @cherrypy.expose
    def index(self):
        return View('Cards').index().render()

    @cherrypy.expose
    def join(self):
        return View('Cards').join().render()

    @cherrypy.expose
    def bid(self, name, card):
        return View('Cards').bid(name, card).render()

    @cherrypy.expose
    def unbid(self, name, card):
        return View('Cards').unbid(name, card).render()

    @cherrypy.expose
    def play(self, name):
        return View('Cards').play(name).render()

# root of webserver filesystem
ROOT=os.path.abspath('.')

config = {'/css': {'tools.staticdir.on': True, 'tools.staticdir.dir': '%s/css' % ROOT},
          '/js' : {'tools.staticdir.on': True, 'tools.staticdir.dir': '%s/js'  % ROOT},
          '/img': {'tools.staticdir.on': True, 'tools.staticdir.dir': '%s/img' % ROOT}}

if 'webfaction' in platform.node():
    cherrypy.config.update ({
        'environment': 'production',
        'log.screen': False,
        'server.socket_host': '127.0.0.1',
        'server.socket_port': 0
    })
else:
    cherrypy.config.update ({
        'server.socket_host': '0.0.0.0',
        'server.socket_port': 8080,
        'log.screen': False,
    })
cherrypy.quickstart(Cards(), config=config)
